package com.insurance.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.insurance.common.common.ResponseData;
import com.insurance.common.constant.ConstantFlag;
import com.insurance.common.dto.PageProposalDto;
import com.insurance.common.dto.ProposalDto;
import com.insurance.common.dto.ProposalStateDto;
import com.insurance.common.enums.CommonEnum;
import com.insurance.common.enums.DeleteFlagEnum;
import com.insurance.common.utils.JwtOperatorUtil;
import com.insurance.common.utils.NumberUtils;
import com.insurance.entity.ProposalEntity;
import com.insurance.enums.ProposalInvoiceStatusEnum;
import com.insurance.enums.ProposalStatusEnum;
import com.insurance.product.entity.ProductEntity;
import com.insurance.product.service.ProductService;
import com.insurance.productcase.entity.ProductCaseEntity;
import com.insurance.productcase.service.ProductCaseService;
import com.insurance.service.ProposalService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Style
 * @version 1.0
 * @date 2021/3/10
 **/
@Api(tags = "投保单服务")
@Slf4j
@RestController
@RequestMapping("/proposal")
public class BodyProposalController {

    //region 注入类

    /**
     * 投保单service
     */
    @Autowired
    private ProposalService proposalService;

    /**
     * 产品service
     */
    @Autowired
    private ProductService productService;

    /**
     * 方案service
     */
    @Autowired
    private ProductCaseService productCaseService;
    //endregion

    //region 分页查询投保单列表

    /**
     * 分页查询投保单列表
     *
     * @param pageProposalDto 查询条件
     * @param userToken 用户凭证
     * @return
     */
    @ApiOperation(value = "分页查询投保单列表")
    @PostMapping("/queryProposalPage")
    public ResponseData<Page<ProposalDto>> queryProposalPage(@RequestBody PageProposalDto pageProposalDto, @RequestHeader(value = "Authorization") String token, @RequestHeader String userToken){
        String userId = "";
        try {
            //校验用户凭证
            if(!JwtOperatorUtil.validateToken(userToken)){
                log.error("【查询投保单列表失败, 用户凭证错误】");
                return ResponseData.error(CommonEnum.USER_TOKEN_ERROR);
            }
            //获取用户主键
            userId = JwtOperatorUtil.getUserId(userToken);
            if(StringUtils.isBlank(userId)){
                log.error("【查询投保单列表失败, 用户为空】");
                return ResponseData.success(CommonEnum.USER_TOKEN_ERROR);
            }
            Page page = new Page(pageProposalDto.getCurrent(), pageProposalDto.getSize());
            ProposalEntity proposalEntity = new ProposalEntity();
            proposalEntity.setCreatePersonId(userId);
            proposalEntity.setProductId(pageProposalDto.getProductId());
            proposalEntity.setProposalId(pageProposalDto.getProposalId());
            proposalEntity.setInsuranceNo(pageProposalDto.getInsuranceNo());
            proposalEntity.setState(pageProposalDto.getState());
            proposalEntity.setInvoiceStatus(pageProposalDto.getInvoiceStatus());
            //分页查询投保单
            Page<ProposalDto> proposalPageInfo = proposalService.queryProposalDtoPage(page, proposalEntity);
            return ResponseData.success(proposalPageInfo);
        } catch (Exception e) {
            log.error("【用户：{}, 查询投保单列表失败, 系统异常：{}】", userId, e.getMessage());
            return ResponseData.error(CommonEnum.SYSTEM_ERROR);
        }
    }
    //endregion

    //region 通过投保单Id查询投保单详情

    /**
     * 通过投保单Id查询投保单详情
     *
     * @param proposalId 投保单主键
     * @return
     */
    @ApiOperation(value = "通过投保单Id查询投保单详情")
    @PostMapping("/getProposalDetail")
    public ResponseData<ProposalDto> getProposalDetail(@RequestBody String proposalId, @RequestHeader(value = "Authorization") String token){
        try {
            //通过主键查询投保单
            ProposalEntity proposal = proposalService.getById(proposalId);
            if(proposal == null){
                log.error("【投保单Id：{}, 通过主键查询投保单失败, 投保单不存在】", proposalId);
                return ResponseData.error(CommonEnum.QUERY_ERROR_NODATA);
            }
            ProposalDto proposalDto = new ProposalDto();
            BeanUtils.copyProperties(proposal, proposalDto);
            return ResponseData.success(proposalDto);
        } catch (Exception e) {
            log.error("【投保单Id：{}, 通过主键查询投保单失败, 系统异常：{}】", proposalId, e.getMessage());
            return ResponseData.error(CommonEnum.SYSTEM_ERROR);
        }
    }
    //endregion

    //region 保存投保单

    /**
     * 保存投保单
     *
     * @param proposalDto 投保单
     * @return
     */
    @ApiOperation(value = "保存投保单")
    @PostMapping("/saveProposal")
    public ResponseData saveProposal(@RequestBody ProposalDto proposalDto, @RequestHeader(value = "Authorization") String token, @RequestHeader String userToken){
        try {
            if(!JwtOperatorUtil.validateToken(userToken)){
                return ResponseData.error(CommonEnum.USER_TOKEN_ERROR);
            }
            log.info("【请求保存保单报文, {}】", JSONUtil.parseObj(proposalDto).toString());
            ProposalEntity proposalEntity = new ProposalEntity();
            BeanUtils.copyProperties(proposalDto, proposalEntity);
            String checkProposal = checkProposal(proposalEntity);
            if(!ConstantFlag.TRUE_STR.equals(checkProposal)){
                return ResponseData.error(checkProposal);
            }
            String appId = JwtOperatorUtil.getAppId(token);
            String userId = JwtOperatorUtil.getUserId(userToken);
            String userName = JwtOperatorUtil.getUserName(userToken);
            proposalEntity.setAppId(appId);
            proposalEntity.setCreateTime(new Date());
            proposalEntity.setCreatePersonId(userId);
            proposalEntity.setCreatePersonName(userName);
            //默认未开发票
            proposalEntity.setInvoiceStatus(StringUtils.isBlank(proposalEntity.getInvoiceStatus()) ? ProposalInvoiceStatusEnum.NOT.getCode() : proposalEntity.getInvoiceStatus());
            proposalEntity.setIdCard(StringUtils.isBlank(proposalEntity.getIdCard()) ? JwtOperatorUtil.getCardId(userToken) : proposalEntity.getIdCard());
            proposalEntity.setTelephone(StringUtils.isBlank(proposalEntity.getTelephone()) ? JwtOperatorUtil.getTelephone(userToken) : proposalEntity.getTelephone());
            proposalEntity.setDeleteFlag(String.valueOf(DeleteFlagEnum.UN_DELETE.getCode()));
            boolean flag = proposalService.save(proposalEntity);
            return flag ? ResponseData.success(proposalEntity.getProposalId()) : ResponseData.error(CommonEnum.SAVE_ERROR);
        } catch (BeansException e) {
            log.error("【保存投保单失败, 系统异常】", e);
            return ResponseData.error(CommonEnum.SYSTEM_ERROR);
        }
    }
    //endregion

    //region 修改投保单状态

    /**
     * 修改投保单状态
     *
     * @param proposalStateDto 投保单
     * @return
     */
    @ApiOperation(value = "修改投保单状态")
    @PostMapping("/changeProposalState")
    public ResponseData changeProposalState(@RequestHeader(value = "Authorization") String token, @RequestHeader String userToken,
                                            @RequestBody ProposalStateDto proposalStateDto){
        if(!JwtOperatorUtil.validateToken(userToken)){
            return ResponseData.error(CommonEnum.USER_TOKEN_ERROR);
        }
        if(proposalStateDto.getProposalId() == null){
            return ResponseData.error("投保单id不能为空");
        }
        if(StringUtils.isBlank(proposalStateDto.getState())){
            return ResponseData.error("投保单状态不能为空");
        }
        //通过投保单id查询投保单对象
        ProposalEntity proposal = proposalService.getById(proposalStateDto.getProposalId());
        if(proposal == null){
            log.error("【投保单Id：{}, 通过主键查询投保单失败, 投保单不存在】", proposalStateDto.getProposalId());
            return ResponseData.error(CommonEnum.QUERY_ERROR_NODATA);
        }
        proposal.setState(proposalStateDto.getState());
        proposal.setUpdateTime(new Date());
        proposal.setUpdatePersonId(JwtOperatorUtil.getUserId(userToken));
        boolean flag = proposalService.updateById(proposal);
        return flag ? ResponseData.success(CommonEnum.OPERATION_SUCCESS) : ResponseData.error(CommonEnum.OPERATION_ERROR);
    }
    //endregion

    //region 校验投保单

    /**
     * 校验投保单
     *
     * @param proposalEntity 投保单对象
     * @return
     */
    public String checkProposal(ProposalEntity proposalEntity){
        try {
            if(proposalEntity.getProductId() == null){
                return "产品id不能为空";
            }
            if(proposalEntity.getCaseId() == null){
                return "方案id不能为空";
            }
            ProductEntity product = productService.getById(proposalEntity.getProductId());
            if(product == null){
                return "产品不存在";
            }
            proposalEntity.setProductName(product.getProductName());
            proposalEntity.setProposalNo(NumberUtils.generateProposalNo(product.getProductCode()));
            if(StringUtils.isBlank(proposalEntity.getInsuranceCompany())){
                proposalEntity.setInsuranceCompany(product.getInsureName());
            }
            List<ProductCaseEntity> productCaseEntityList = productCaseService.queryListByProductId(proposalEntity.getProductId());
            if(CollectionUtils.isEmpty(productCaseEntityList)){
                return "方案不存在";
            }
            log.info("【通过产品id：{}查询, 查询到产品方案：{}个】", proposalEntity.getProductId(), productCaseEntityList.size());
            List<String> caseIdList = productCaseEntityList.stream().map(ProductCaseEntity::getCaseId).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(caseIdList)){
                for(String cid : caseIdList){
                    log.info("【方案id：{}】", cid);
                }
            }

            if(!caseIdList.contains(proposalEntity.getCaseId())){
                return "方案不在此产品中";
            }
            for(ProductCaseEntity productCaseEntity : productCaseEntityList){
                if(proposalEntity.getCaseId().equals(productCaseEntity.getCaseId())){
                    proposalEntity.setCaseName(productCaseEntity.getCaseName());
                    break;
                }
            }
            if(proposalEntity.getCreateTime() == null){
                proposalEntity.setCreateTime(new Date());
            }
            if(StringUtils.isBlank(proposalEntity.getState())){
                proposalEntity.setState(ProposalStatusEnum.SAVE.getCode());
            }
            return ConstantFlag.TRUE_STR;
        } catch (Exception e) {
            log.error("【校验投保单数据异常】", e);
            return "数据校验异常";
        }
    }
    //endregion

    //region 修改投保单

    /**
     * 修改投保单
     *
     * @param proposalDto 投保单
     * @return
     */
    @ApiOperation(value = "修改投保单")
    @PostMapping("/editProposal")
    public ResponseData editProposal(@RequestBody ProposalDto proposalDto, @RequestHeader(value = "Authorization") String token, @RequestHeader String userToken){
        try {
            if(!JwtOperatorUtil.validateToken(userToken)){
                return ResponseData.error(CommonEnum.USER_TOKEN_ERROR);
            }
            String proposalId = proposalDto.getProposalId();
            if(StringUtils.isBlank(proposalId)){
                log.error("【修改投保单失败, 投保单不存在：{}】", proposalId);
                return ResponseData.error(CommonEnum.QUERY_ERROR_NODATA);
            }
            ProposalEntity proposalEntity = new ProposalEntity();
            BeanUtils.copyProperties(proposalDto, proposalEntity);
            String checkProposal = checkProposal(proposalEntity);
            if(!ConstantFlag.TRUE_STR.equals(checkProposal)){
                log.error("【修改投保单失败, 数据校验失败：{}】", checkProposal);
                return ResponseData.error(checkProposal);
            }
            String appId = JwtOperatorUtil.getAppId(token);
            String userId = JwtOperatorUtil.getUserId(userToken);
            String userName = JwtOperatorUtil.getUserName(userToken);
            proposalEntity.setAppId(appId);
            proposalEntity.setCreateTime(new Date());
            proposalEntity.setCreatePersonId(userId);
            proposalEntity.setCreatePersonName(userName);
            proposalEntity.setIdCard(StringUtils.isBlank(proposalEntity.getIdCard()) ? JwtOperatorUtil.getCardId(userToken) : proposalEntity.getIdCard());
            proposalEntity.setTelephone(StringUtils.isBlank(proposalEntity.getTelephone()) ? JwtOperatorUtil.getTelephone(userToken) : proposalEntity.getTelephone());
            proposalEntity.setUpdateTime(new Date());
            proposalEntity.setUpdatePersonId(userId);
            boolean flag = proposalService.updateById(proposalEntity);
            return flag ? ResponseData.success(proposalEntity.getProposalId()) : ResponseData.error(CommonEnum.UPDATE_ERROR);
        } catch (BeansException e) {
            log.error("【修改投保单失败, 系统异常】", e);
            return ResponseData.error(CommonEnum.SYSTEM_ERROR);
        }
    }
    //endregion

    @ApiOperation(value = "删除投保单")
    @PostMapping("/removeProposal")
    public ResponseData removeProposal(@RequestBody String proposalId, @RequestHeader(value = "Authorization") String token, @RequestHeader String userToken){
        try {
            if(!JwtOperatorUtil.validateToken(userToken)){
                return ResponseData.error(CommonEnum.USER_TOKEN_ERROR);
            }
            ProposalEntity proposalEntity = proposalService.getById(proposalId);
            if(proposalEntity == null){
                log.error("【删除投保单失败, 投保单不存在】");
                return ResponseData.error(CommonEnum.QUERY_ERROR_NODATA);
            }
            proposalEntity.setDeleteFlag(String.valueOf(DeleteFlagEnum.DELETE.getCode()));
            proposalEntity.setUpdateTime(new Date());
            proposalEntity.setUpdatePersonId(JwtOperatorUtil.getUserId(userToken));
            boolean flag = proposalService.updateById(proposalEntity);
            return flag ? ResponseData.success(proposalEntity.getProposalId()) : ResponseData.error(CommonEnum.DELETE_ERROR);
        } catch (Exception e) {
            log.error("【删除投保单失败, 系统异常】", e);
            return ResponseData.error(CommonEnum.SYSTEM_ERROR);
        }
    }

}
